home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 4364 / 4364.xpi / chrome / elemhidehelper.jar / content / composer.js < prev    next >
Text File  |  2009-07-01  |  17KB  |  586 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Adblock Plus Element Hiding Helper.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Wladimir Palant.
  18.  * Portions created by the Initial Developer are Copyright (C) 2006-2009
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *
  23.  * ***** END LICENSE BLOCK ***** */
  24.  
  25. var domainData;
  26. var nodeData;
  27. var selectedNode = null;
  28. var advancedMode = false;
  29. var treeView = null;
  30. var stylesheetURL;
  31. var previewStyle = null;
  32. var doc;
  33.  
  34. /*******************
  35.  * NodeData object *
  36.  *******************/
  37.  
  38. function NodeData(node, parentNode) {
  39.     this.tagName = {value: node.tagName, checked: false};
  40.  
  41.     if (typeof parentNode == "undefined")
  42.         parentNode = (node.parentNode && node.parentNode.nodeType == node.ELEMENT_NODE ? new NodeData(node.parentNode) : null);
  43.     this.parentNode = parentNode;
  44.  
  45.     var prevSibling = node.previousSibling;
  46.     while (prevSibling && prevSibling.nodeType != node.ELEMENT_NODE)
  47.         prevSibling = prevSibling.previousSibling;
  48.     this.prevSibling = (prevSibling ? new NodeData(prevSibling, this.parentNode) : null);
  49.  
  50.     if (parentNode && !prevSibling)
  51.         this.firstChild = {checked: false};
  52.  
  53.     var nextSibling = node.nextSibling;
  54.     while (nextSibling && nextSibling.nodeType != node.ELEMENT_NODE)
  55.         nextSibling = nextSibling.nextSibling;
  56.     if (parentNode && !nextSibling)
  57.         this.lastChild = {checked: false};
  58.  
  59.     this.attributes = [];
  60.     for (var i = 0; i < node.attributes.length; i++) {
  61.         var attribute = node.attributes[i];
  62.         var data = {name: attribute.name, value: attribute.value, selected: attribute.value, checked: false};
  63.         if (data.name == "id" || data.name == "class")
  64.             this.attributes.unshift(data);
  65.         else
  66.             this.attributes.push(data);
  67.     }
  68.  
  69.     if (this.attributes.length >= 2 && this.attributes[1].name == "id") {
  70.         // Make sure ID attribute comes first
  71.         var tmp = this.attributes[1];
  72.         this.attributes[1] = this.attributes[0];
  73.         this.attributes[0] = tmp;
  74.     }
  75.  
  76.     this.customCSS = {selected: "", checked: false};
  77. }
  78.  
  79. /*******************
  80.  * TreeView object *
  81.  *******************/
  82.  
  83. function TreeView(tree) {
  84.     var origView = tree.view;
  85.     this.getRowProperties = TreeView_getRowProperties;
  86.     this.getCellProperties = TreeView_getCellProperties;
  87.  
  88.     createQIProxy(this, origView);
  89.  
  90.     for (var key in origView) {
  91.         if (this.hasOwnProperty(key))
  92.             continue;
  93.  
  94.         createPropertyProxy(this, origView, key);
  95.     }
  96.  
  97.     tree.view = this;
  98. }
  99.  
  100. function createQIProxy(obj, orig) {
  101.     obj.QueryInterface = function(iid) {
  102.         var impl = orig.QueryInterface(iid);
  103.         if (impl != orig)
  104.             throw Components.results.NS_ERROR_NO_INTERFACE;
  105.  
  106.         return obj;
  107.     };
  108. }
  109.  
  110. function createPropertyProxy(obj, orig, key) {
  111.     if (typeof orig[key] == "function") {
  112.         obj[key] = function() {
  113.             return orig[key].apply(orig, arguments);
  114.         };
  115.     }
  116.     else {
  117.         obj.__defineGetter__(key, function() {
  118.             return orig[key];
  119.         });
  120.         obj.__defineSetter__(key, function(value) {
  121.             orig[key] = value;
  122.         });
  123.     }
  124. }
  125.  
  126. var atomService = Components.classes["@mozilla.org/atom-service;1"]
  127.                                                         .getService(Components.interfaces.nsIAtomService);
  128. var selectedAtom = atomService.getAtom("selected-false");
  129. var anchorAtom = atomService.getAtom("anchor");
  130.  
  131. function TreeView_getRowProperties(row, properties) {
  132.     if (!this.selection.isSelected(row))
  133.         properties.AppendElement(selectedAtom);
  134.  
  135.     var item = this.getItemAtIndex(row);
  136.     if (item && (item.nodeData.expression != "*" || item.nodeData == nodeData))
  137.         properties.AppendElement(anchorAtom);
  138. }
  139.  
  140. function TreeView_getCellProperties(row, col, properties) {
  141.     this.getRowProperties(row, properties);
  142. }
  143.  
  144. /*********************
  145.  * General functions *
  146.  *********************/
  147.  
  148. function init() {
  149.     var element = window.arguments[0];
  150.     doc = element.ownerDocument;
  151.     var wnd = doc.defaultView;
  152.  
  153.     var geckoVersion = "0.0";
  154.     if ("nsIXULAppInfo" in  Components.interfaces)
  155.             geckoVersion = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo).platformVersion;
  156.     var versionComparator = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
  157.                                                                         .createInstance(Components.interfaces.nsIVersionComparator);
  158.     if (versionComparator.compare(geckoVersion, "1.9") < 0)
  159.     {
  160.         // Gecko 1.8 does not support horizontal scrolling for trees,
  161.         // change width attribute into flex for tree columns.
  162.         var nodeCol = document.getElementById("nodes-tree-node");
  163.         nodeCol.setAttribute("flex", "2");
  164.         nodeCol.nextSibling.removeAttribute("resizeafter");
  165.  
  166.         var idCol = document.getElementById("nodes-tree-id");
  167.         idCol.setAttribute("flex", "1");
  168.         if (!idCol.hasAttribute("hidden"))
  169.             idCol.setAttribute("hidden", "true");
  170.         idCol.nextSibling.removeAttribute("resizeafter");
  171.  
  172.         var classCol = document.getElementById("nodes-tree-class");
  173.         classCol.setAttribute("flex", "1");
  174.         if (!classCol.hasAttribute("hidden"))
  175.             classCol.setAttribute("hidden", "true");
  176.         classCol.parentNode.removeChild(classCol.nextSibling);
  177.     }
  178.  
  179.     nodeData = new NodeData(element);
  180.     nodeData.tagName.checked = true;
  181.     if (nodeData.attributes.length > 0) {
  182.         if (nodeData.attributes[0].name == "id" || nodeData.attributes[0].name == "class") {
  183.             nodeData.attributes[0].selected = nodeData.attributes[0].value;
  184.             nodeData.attributes[0].checked = true;
  185.         }
  186.         else {
  187.             var maxLen = 0;
  188.             var bestAttr = null;
  189.             for (var i = 0; i < nodeData.attributes.length; i++) {
  190.                 if (nodeData.attributes[i].value.length > maxLen) {
  191.                     maxLen = nodeData.attributes[i].value.length;
  192.                     bestAttr = nodeData.attributes[i];
  193.                 }
  194.             }
  195.             if (bestAttr) {
  196.                 bestAttr.selected = bestAttr.value;
  197.                 bestAttr.checked = true;
  198.             }
  199.         }
  200.     }
  201.  
  202.     var domain = wnd.location.hostname;
  203.     var selectedDomain = domain.replace(/^www\./, "");
  204.     domainData = {value: domain, selected: selectedDomain};
  205.  
  206.     fillDomains(domainData);
  207.     fillNodes(nodeData);
  208.     setAdvancedMode(document.documentElement.getAttribute("advancedMode") == "true");
  209.     updateExpression();
  210.  
  211.     setTimeout(function() {
  212.         document.getElementById("domainGroup").selectedItem.focus();
  213.         if (document.getElementById("preview").checked)
  214.             togglePreview(true);
  215.     }, 0);
  216. }
  217.  
  218. function updateExpression() {
  219.     var curNode = nodeData;
  220.     while (curNode) {
  221.         let expression = (curNode.tagName.checked ? curNode.tagName.value : "*");
  222.  
  223.         for (var i = 0; i < curNode.attributes.length; i++) {
  224.             var attr = curNode.attributes[i];
  225.  
  226.             if (attr.checked) {
  227.                 var escapedName = attr.name.replace(/([^\w\-])/g, "\\$1")
  228.                                                                      .replace(/\\\{/g, "\\7B ")
  229.                                                                      .replace(/\\\}/g, "\\7D ");
  230.                 if (attr.selected != "") {
  231.                     var op = "*=";
  232.                     if (attr.selected == attr.value)
  233.                         op = "=";
  234.                     else if (attr.value.substr(0, attr.selected.length) == attr.selected)
  235.                         op = "^=";
  236.                     else if (attr.value.substr(attr.value.length - attr.selected.length) == attr.selected)
  237.                         op = "$=";
  238.     
  239.                     if (attr.name == "id" && op == "=" && !/[^\w\-]/.test(attr.selected))
  240.                         expression += "#" + attr.selected;
  241.                     else if (attr.name == "class" && op == "=" && !/[^\w\-\s]/.test(attr.selected) && /\S/.test(attr.selected)) {
  242.                         var classes = attr.selected.split(/\s+/);
  243.                         for (var j = 0; j < classes.length; j++) {
  244.                             if (classes[j] == "")
  245.                                 continue;
  246.  
  247.                             expression += "." + classes[j];
  248.                         }
  249.                     }
  250.                     else {
  251.                         var escapedValue = attr.selected.replace(/"/g, '\\"')
  252.                                                                                         .replace(/\{/, "\\7B ")
  253.                                                                                         .replace(/\}/, "\\7D ");
  254.                         expression += "[" + escapedName + op + '"' + escapedValue + '"' + "]";
  255.                     }
  256.                 }
  257.                 else {
  258.                     expression += "[" + escapedName + "]";
  259.                 }
  260.             }
  261.         }
  262.  
  263.         if (curNode.customCSS.checked && curNode.customCSS.selected != "")
  264.         {
  265.             expression += curNode.customCSS.selected
  266.                                                                                 .replace(/\{/, "\\7B ")
  267.                                                                                 .replace(/\}/, "\\7D ");
  268.         }
  269.  
  270.         if ("firstChild" in curNode && curNode.firstChild.checked)
  271.             expression += ":first-child";
  272.         if ("lastChild" in curNode && curNode.lastChild.checked)
  273.             expression += ":last-child";
  274.  
  275.         curNode.expression = expression;
  276.  
  277.         if (curNode.prevSibling)
  278.             curNode = curNode.prevSibling;
  279.         else
  280.             curNode = curNode.parentNode;
  281.     }
  282.  
  283.     let expression = nodeData.expression;
  284.  
  285.     var isParent = false;
  286.     var isRemoteParent = false;
  287.     var siblingCount = 0;
  288.     var firstRun = true;
  289.  
  290.     var curData = nodeData;
  291.     while (curData) {
  292.         if (!firstRun && curData.expression != "*") {
  293.             var parentRelation = "";
  294.             if (isRemoteParent)
  295.                 parentRelation = " ";
  296.             else if (isParent)
  297.                 parentRelation = " > ";
  298.  
  299.             var siblingRelation = "";
  300.             for (var i = 0; i < siblingCount; i++)
  301.                 siblingRelation += "* + ";
  302.             siblingRelation = siblingRelation.replace(/^\*/, '');
  303.  
  304.             var relation;
  305.             if (parentRelation != "" && siblingRelation != "")
  306.                 relation = siblingRelation + "*" + parentRelation;
  307.             else if (parentRelation != "")
  308.                 relation = parentRelation;
  309.             else
  310.                 relation = siblingRelation;
  311.  
  312.             expression = curData.expression + relation + expression;
  313.  
  314.             isParent = false;
  315.             isRemoteParent = false;
  316.             siblingCount = 0;
  317.         }
  318.         firstRun = false;
  319.  
  320.         if (curData.prevSibling) {
  321.             siblingCount++;
  322.             curData = curData.prevSibling;
  323.         }
  324.         else if (curData.parentNode) {
  325.             siblingCount = 0;
  326.             if (isParent)
  327.                 isRemoteParent = true;
  328.             else
  329.                 isParent = true;
  330.             curData = curData.parentNode;
  331.         }
  332.         else
  333.             curData = null;
  334.     }
  335.  
  336.     stylesheetURL = "data:text/css," + encodeURIComponent(expression + "{display: none !important;}");
  337.     expression = domainData.selected + "##" + expression;
  338.  
  339.     document.getElementById("expression").value = expression;
  340.  
  341.     var tree = document.getElementById("nodes-tree");
  342.     if (tree.view && tree.view.selection)
  343.         tree.treeBoxObject.invalidateRow(tree.view.selection.currentIndex);
  344.  
  345.     if (previewStyle)
  346.         previewStyle.setAttribute("href", stylesheetURL);
  347. }
  348.  
  349. function fillDomains(domainData) {
  350.     var list = document.getElementById("domainGroup");
  351.  
  352.     var commandHandler = function() {
  353.         changeDomain(this);
  354.     };
  355.  
  356.     var node = document.createElement("radio");
  357.     node.setAttribute("label", list.getAttribute("_labelnone"));
  358.     node.setAttribute("value", "");
  359.     node.addEventListener("command", commandHandler, false);
  360.     if (domainData.selected == "")
  361.         node.setAttribute("selected", "true");
  362.     list.appendChild(node);
  363.  
  364.     var parts = domainData.value.split(".");
  365.     if (parts[0] == "")
  366.         parts.splice(0, 1);
  367.  
  368.     for (var i = 1; i <= parts.length; i++) {
  369.         var curDomain = parts.slice(parts.length - i).join(".");
  370.  
  371.         node = document.createElement("radio");
  372.         node.setAttribute("label", curDomain)
  373.         node.setAttribute("value", curDomain);
  374.         node.addEventListener("command", commandHandler, false);
  375.         if (domainData.selected == curDomain)
  376.             node.setAttribute("selected", "true");
  377.         list.appendChild(node);
  378.     }
  379. }
  380.  
  381. function fillNodes(nodeData) {
  382.     var curContainer = document.createElement("treechildren");
  383.     var curChildren = null;
  384.     while (nodeData) {
  385.         var id = "";
  386.         var className = "";
  387.         var i = 0;
  388.         if (nodeData.attributes.length > i && nodeData.attributes[i].name == "id")
  389.             id = nodeData.attributes[i++].value;
  390.         if (nodeData.attributes.length > i && nodeData.attributes[i].name == "class")
  391.             className = nodeData.attributes[i++].value;
  392.  
  393.         var item = document.createElement("treeitem");
  394.         var row = document.createElement("treerow");
  395.  
  396.         var cell = document.createElement("treecell");
  397.         cell.setAttribute("label", nodeData.tagName.value);
  398.         row.appendChild(cell);
  399.  
  400.         cell = document.createElement("treecell");
  401.         cell.setAttribute("label", id);
  402.         row.appendChild(cell);
  403.  
  404.         cell = document.createElement("treecell");
  405.         cell.setAttribute("label", className);
  406.         row.appendChild(cell);
  407.  
  408.         item.appendChild(row);
  409.         item.nodeData = nodeData;
  410.  
  411.         if (curChildren) {
  412.             item.appendChild(curChildren);
  413.             item.setAttribute("container", "true");
  414.             item.setAttribute("open", "true");
  415.         }
  416.         curChildren = null;
  417.  
  418.         if (curContainer.firstChild)
  419.             curContainer.insertBefore(item, curContainer.firstChild);
  420.         else
  421.             curContainer.appendChild(item);
  422.  
  423.         if (nodeData.prevSibling)
  424.             nodeData = nodeData.prevSibling;
  425.         else if (nodeData.parentNode) {
  426.             curChildren = curContainer;
  427.             curContainer = document.createElement("treechildren");
  428.             nodeData = nodeData.parentNode;
  429.         }
  430.         else
  431.             nodeData = null;
  432.     }
  433.  
  434.     var tree = document.getElementById("nodes-tree");
  435.     var body = document.getElementById("nodes-tree-children");
  436.     while (curContainer.firstChild)
  437.         body.appendChild(curContainer.firstChild);
  438. }
  439.  
  440. function fillAttributes(nodeData) {
  441.     selectedNode = nodeData;
  442.  
  443.     var list = document.getElementById("attributes-list");
  444.     while(list.firstChild)
  445.         list.removeChild(list.firstChild);
  446.  
  447.     // Add tag name entry
  448.     var node = document.createElement("attribute");
  449.     node.attr = nodeData.tagName;
  450.     node.setAttribute("notextbox", "true");
  451.     node.setAttribute("checked", nodeData.tagName.checked);
  452.     node.setAttribute("label", list.getAttribute("_labeltagname") + " " + nodeData.tagName.value);
  453.     list.appendChild(node);
  454.  
  455.     // Add first/last child entries
  456.     if (advancedMode && "firstChild" in nodeData) {
  457.         node = document.createElement("attribute");
  458.         node.attr = nodeData.firstChild;
  459.         node.setAttribute("notextbox", "true");
  460.         node.setAttribute("checked", nodeData.firstChild.checked);
  461.         node.setAttribute("label", list.getAttribute("_labelfirstchild"));
  462.         list.appendChild(node);
  463.     }
  464.     if (advancedMode && "lastChild" in nodeData) {
  465.         node = document.createElement("attribute");
  466.         node.attr = nodeData.lastChild;
  467.         node.setAttribute("notextbox", "true");
  468.         node.setAttribute("checked", nodeData.lastChild.checked);
  469.         node.setAttribute("label", list.getAttribute("_labellastchild"));
  470.         list.appendChild(node);
  471.     }
  472.  
  473.     // Add attribute entries
  474.     for (var i = 0; i < nodeData.attributes.length; i++) {
  475.         var attr = nodeData.attributes[i];
  476.  
  477.         node = document.createElement("attribute");
  478.         node.attr = attr;
  479.         node.setAttribute("checked", attr.checked);
  480.         node.setAttribute("label", attr.name + ": " + attr.value);
  481.         node.setAttribute("value", attr.selected);
  482.         list.appendChild(node);
  483.     }
  484.  
  485.     if (advancedMode) {
  486.         // Add custom CSS entry
  487.         node = document.createElement("attribute");
  488.         node.attr = nodeData.customCSS;
  489.         node.setAttribute("checked", nodeData.customCSS.checked);
  490.         node.setAttribute("label", list.getAttribute("_labelcustom"));
  491.         node.setAttribute("value", nodeData.customCSS.selected);
  492.         list.appendChild(node);
  493.     }
  494. }
  495.  
  496. function togglePreview(preview) {
  497.     if (preview) {
  498.         if (!previewStyle || !previewStyle.parentNode) {
  499.             previewStyle = doc.createElementNS("http://www.w3.org/1999/xhtml", "link");
  500.             previewStyle.setAttribute("rel", "stylesheet");
  501.             previewStyle.setAttribute("type", "text/css");
  502.             doc.documentElement.appendChild(previewStyle);
  503.         }
  504.         previewStyle.setAttribute("href", stylesheetURL);
  505.     }
  506.     else {
  507.         if (previewStyle && previewStyle.parentNode)
  508.             previewStyle.parentNode.removeChild(previewStyle);
  509.         previewStyle = null;
  510.     }
  511. }
  512.  
  513. function changeDomain(node) {
  514.     domainData.selected = node.getAttribute("value");
  515.     updateExpression();
  516. }
  517.  
  518. function toggleAttr(node) {
  519.     node.attr.checked = node.checked;
  520.     updateExpression();
  521. }
  522.  
  523. function setSelectedAttrValue(node) {
  524.     node.attr.selected = node.value;
  525.     if (node.attr.checked)
  526.         updateExpression();
  527. }
  528.  
  529. function setAdvancedMode(mode) {
  530.     advancedMode = mode;
  531.  
  532.     var dialog = document.documentElement;
  533.     dialog.setAttribute("advancedMode", advancedMode);
  534.  
  535.     var button = dialog.getButton("disclosure");
  536.     button.setAttribute("label", dialog.getAttribute(advancedMode ? "buttonlabeldisclosure_off" : "buttonlabeldisclosure_on"));
  537.  
  538.     fillAttributes(nodeData);
  539.  
  540.     if (advancedMode) {
  541.         setTimeout(function() {
  542.             var tree = document.getElementById("nodes-tree");
  543.  
  544.             if (!treeView)
  545.                 treeView = new TreeView(tree);
  546.  
  547.             if (selectedNode) {
  548.                 // Expand all containers
  549.                 var items = tree.getElementsByTagName("treeitem");
  550.                 for (var i = 0; i < items.length; i++)
  551.                     if (items[i].getAttribute("container") == "true")
  552.                         items[i].setAttribute("open", "true");
  553.  
  554.                 tree.treeBoxObject.ensureRowIsVisible(tree.view.rowCount - 1);
  555.                 tree.view.selection.select(tree.view.rowCount - 1);
  556.             }
  557.         }, 0);
  558.     }
  559. }
  560.  
  561. function updateNodeSelection() {
  562.     var tree = document.getElementById("nodes-tree");
  563.     var selection = tree.view.selection;
  564.     if (selection.count < 1)
  565.         return;
  566.  
  567.     var min = {};
  568.     selection.getRangeAt(0, min, {});
  569.  
  570.     var item = tree.view
  571.                                  .QueryInterface(Components.interfaces.nsITreeContentView)
  572.                                  .getItemAtIndex(min.value);
  573.     if (!item || !item.nodeData)
  574.         return;
  575.  
  576.     fillAttributes(item.nodeData);
  577. }
  578.  
  579. function addExpression() {
  580.     var abp = Components.classes["@mozilla.org/adblockplus;1"]
  581.                                             .createInstance().wrappedJSObject;
  582.     abp.addPatterns([document.getElementById("expression").value], 1);
  583.  
  584.     togglePreview(true);
  585. }
  586.